package com.common.sdk.net.connect.http.util;

import java.util.AbstractQueue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import com.common.sdk.net.connect.interfaces.IQueueFull;

/**
 * LIFO List
 * 后进先出同步队列，如果List的size大于maxSize，则删除尾部的一个Item，然后在头部添加一个Item，每次take一条Item，会从头部获取。
 * 
 * @author boyang116245
 * @param <E>
 */
public class LimitedStackQueue<E> extends AbstractQueue<E> {

    public final int maxSize;

    private IQueueFull<E> queueFull;

    public LimitedStackQueue(int maxSize) {
        this(maxSize, null);
    }

    public LimitedStackQueue(int maxSize, IQueueFull<E> queueFull) {
        super();
        this.maxSize = maxSize;
        this.queueFull = queueFull;
        lock = new ReentrantLock();
    }

    public List<E> mList = Collections.synchronizedList(new ArrayList<E>());

    /** Main lock guarding all access */
    final ReentrantLock lock;

    /**
     * get list size
     * 
     * @return
     */
    public synchronized int size() {
        return mList.size();
    }

    @Override
    public synchronized boolean contains(Object item) {

        if (!mList.isEmpty()) {
            if (mList.contains(item)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean offer(E item) {

        final ReentrantLock lock = this.lock;
        lock.lock();

        try {
            E removeItem = null;
            int size = mList.size();
            if (size >= maxSize) {
                int pos = mList.size() - 1;
                removeItem = mList.remove(pos);
                if (queueFull != null) {
                    queueFull.queueFullWhenOffer(removeItem);
                }
            }
            mList.add(0, item);

            if (size >= maxSize) {
                return false;
            } else {
                return true;
            }

        } finally {
            lock.unlock();
        }
    }

    @Override
    public E poll() {

        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (!mList.isEmpty()) {
                return mList.remove(0);
            }
        } finally {
            lock.unlock();
        }

        return null;
    }

    @Override
    public E peek() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator<E> iterator() {
        throw new UnsupportedOperationException();
    }
}
